:- import "%%/lib/list.sl" #

is.transitive .tr :- is.atom .tr, char.at .tr 0 "%%" #

is.wildcard .wc :- is.atom .wc, char.at .wc 0 ".", length .wc 1 #

is.variable .var :- is.atom .var, char.at .var 0 "." #


-- Clause Identification --

traverse.clauses .pred .clause :-
	recognize.construct .pred:. .list !
	list.member .list (.sub .),
	traverse.clauses .sub .clause #
traverse.clauses .pred .clause :-
	recognize.clause .pred:. .list !
	list.member .list (.sub .),
	traverse.clauses .sub .clause;
	.clause = .pred #
traverse.clauses .pred .pred #

transform.clauses .tr .args .cb :-
	recognize.construct .tr .clauses !
	transform.clauseList .clauses .args .cb #
transform.clauses .obj0:.obj1 .arg0:.arg1 .cb :-
	recognize.clause .obj0:.obj .list !
	transform.clauseList .list .arg0:.arg1 .cb,
	local .arg0 .arg1 (.arg0 = .obj, .cb, .arg1 = .obj1) #
transform.clauses .obj0:.obj1 .arg0:.arg1 .cb :-
	local .arg0 .arg1 (.arg0 = .obj0, .cb, .arg1 = .obj1) #

transform.clauseList $ . . #
transform.clauseList (.trans, .remains) .args .cb :-
	transform.clauses .trans .args .cb,
	transform.clauseList .remains .args .cb #

recognize.construct (.p0, .q0):(.p1, .q1) (.p0:.p1, .q0:.q1,) #
recognize.construct (.p0; .q0):(.p1; .q1) (.p0:.p1, .q0:.q1,) #
recognize.construct ((.p0 ! .q0)):((.p1 ! .q1)) (.p0:.p1, .q0:.q1,) #
recognize.construct ((.p0 :- .q0)):((.p1 :- .q1)) (.p0:.p1, .q0:.q1,) #
recognize.construct (findall .v .p0 .l):(findall .v .p1 .l) (.p0:.p1,) #
recognize.construct (finally .p0 .q0):(finally .p1 .q1) (.p0:.p1, .q0:.q1,) #
recognize.construct (forall .p0 .q0):(forall .p1 .q1) (.p0:.p1, .q0:.q1,) #
recognize.construct (if .p0 then .q0):(if .p1 then .q1) (.p0:.p1, .q0:.q1,) #
recognize.construct (if .p0 then .q0 else .r0):(if .p1 then .q1 else .r1)
	(.p0:.p1, .q0:.q1, .r0:.r1,) #
recognize.construct (once .p0):(once .p1) (.p0:.p1,) #
recognize.construct (spawn .p0):(spawn .p1) (.p0:.p1,) #
recognize.construct .sel0:.sel1 .clauses :-
	nth .sel0 0 select !
	length .sel0 .len, length .sel1 .len,
	nth .sel1 0 select,
	recognize.select .sel0:.sel1 1 .clauses #

recognize.select .sel0:.sel1 .n $ :-
	length .sel0 .n ! #
recognize.select .sel0:.sel1 .n .clauses :-
	nth .sel0 .n .p0, nth .sel1 .n .p1,
	recognize.case .p0:.p1 .clauses .t,
	let .n1 (.n + 1), recognize.select .sel0:.sel1 .n1 .t #

recognize.case (.p0 => .q0):(.p1 => .q1) (.p0:.p1, .q0:.q1, .t) .t :- ! #
recognize.case .p0:.p1 (.p0:.p1, .t) .t #

recognize.clause (synchronized .a .p0):(synchronized .a .p1) (.p0:.p1,) #
recognize.clause (trail .p0):(trail .p1) (.p0:.p1,) #
recognize.clause (.try0):(.try1) (.p0:.p1,) :-
	nth .try0 0 try,
	length .try0 .len, length .try1 .len,
	nth .try1 0 try,
	nth .try0 1 .p0, nth .try1 1 .p1,
	mnth .try0 2 0 .catches, mnth .try1 2 0 .catches #


-- System Predicates --

systemCall ($ / 1) #
systemCall (ascii / 3) #
systemCall (assert / .) #
systemCall (bound / 2) #
systemCall (compare / 3) #
systemCall (concat / .) #
systemCall (dump / .) #
systemCall (exec / 2) #
systemCall (exec / 3) #
systemCall (expr / 3) #
systemCall (fail / 1) #
systemCall (generalize / 3) #
systemCall (get / 3) #
systemCall (get.all / 3) #
systemCall (home.dir / 2) #
systemCall (infix / 5) #
systemCall (int / 2) #
systemCall (is.atom / 2) #
systemCall (is.number / 2) #
systemCall (is.string / 2) #
systemCall (is.tree / 2) #
systemCall (is.tuple / 2) #
systemCall (length / 3) #
systemCall (let / 3) #
systemCall (local / .) #
systemCall (mnth / 5) #
systemCall (nl / 1) #
systemCall (not / .) #
systemCall (nth / 4) #
systemCall (once / 2) #
systemCall (parse / 3) #
systemCall (put / 2) #
systemCall (quit / 1) #
systemCall (quit / 2) #
systemCall (raise / 2) #
systemCall (repeat / 1) #
systemCall (rule / 2) #
systemCall (same / 3) #
systemCall (select / .) #
systemCall (set / 3) #
systemCall (set.pointer / 3) #
systemCall (stream.close / 2) #
systemCall (stream.createBuffer / 2) #
systemCall (stream.dump / 3) #
systemCall (stream.eof / 2) #
systemCall (stream.flush / 2) #
systemCall (stream.get / 3) #
systemCall (stream.line / 3) #
systemCall (stream.nl / 2) #
systemCall (stream.peek / 3) #
systemCall (stream.put / 3) #
systemCall (stream.popen / 3) #
systemCall (stream.readFile / 3) #
systemCall (stream.stdin / 2) #
systemCall (stream.stdout / 2) #
systemCall (stream.write / 3) #
systemCall (stream.writeFile / 3) #
systemCall (substr / 5) #
systemCall (synchronized / 3) #
systemCall (trail / 2) #
systemCall (try / .) #
systemCall (unset / 2) #
systemCall (write / .) #
systemCall (yes / 1) #
